﻿using Microsoft.AspNetCore.Http;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace Link_eLab.Helper
{
    public static class FileHelper
    {
        #region 判断是否为图片

        /// <summary>
        /// 判断是否为图片
        /// </summary>
        /// <param name="data"></param>
        /// <returns>JSON结果集</returns>
        public static bool IsImage(byte[] data)
        {
            var dataIsImage = false;
            using (var imageReadStream = new MemoryStream(data))
            {
                try
                {
                    using (var possibleImage = Image.FromStream(imageReadStream))
                    {
                    }
                    dataIsImage = true;
                }
                catch
                {
                    dataIsImage = false;
                }
            }

            return dataIsImage;
        }

        #endregion

        #region 制作缩略图

        /// <summary>
        /// 制作缩略图
        /// </summary>
        /// <param name="original">图片对象</param>
        /// <param name="newFileName">新图路径</param>
        /// <param name="maxWidth">最大宽度</param>
        /// <param name="maxHeight">最大高度</param>
        public static void ThumbImg(Image original, string newFileName, int maxWidth, int maxHeight)
        {
            Size newSize = ResizeImage(original.Width, original.Height, maxWidth, maxHeight);
            using Image displayImage = new Bitmap(original, newSize);
            try
            {
                displayImage.Save(newFileName, original.RawFormat);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                original.Dispose();
            }
        }

        #endregion

        #region 制作缩略图

        /// <summary>
        /// 制作缩略图
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="newFileName">新图路径</param>
        /// <param name="maxWidth">最大宽度</param>
        /// <param name="maxHeight">最大高度</param>
        public static void ThumbImg(string fileName, string newFileName, int maxWidth, int maxHeight)
        {
            byte[] imageBytes = File.ReadAllBytes(fileName);
            Image img = Image.FromStream(new MemoryStream(imageBytes));
            ThumbImg(img, newFileName, maxWidth, maxHeight); 
        }

        #endregion

        #region 制作缩略图并上传到FTP服务器

        /// <summary>
        /// 制作缩略图并上传到FTP服务器
        /// </summary>
        /// <param name="fileName">FTP文件路径及文件名</param>
        /// <param name="newFileName">生成的文件名</param>
        /// <param name="path">上传路径</param>
        /// <param name="maxWidth">最大宽度</param>
        /// <param name="maxHeight">最大高度</param>
        public static void UploadThumbImg(string fileName, string newFileName, string path, int maxWidth, int maxHeight)
        {
            // 获取服务器端图片并转换为 byte 数组
            var contents = FtpHelper.GetFtpBase64String(fileName);
            byte[] imageBytes = Convert.FromBase64String(contents);

            // 如果图片数组长度大于0时则继续操作
            if (imageBytes.Length > 0)
            {
                // 读取图片字节数组并转换为 image 对象
                Image img = Image.FromStream(new MemoryStream(imageBytes));

                // 重新设置图片大小
                Size newSize = ResizeImage(img.Width, img.Height, maxWidth, maxHeight);
                using Image displayImage = new Bitmap(img, newSize);
                try
                {
                    // 将图片重新转换为Byte数组
                    byte[] newImageBytes = ImageToBytes(displayImage);

                    // 执行上传文件方法
                    FtpHelper.FileUpLoad(newImageBytes, $"{newFileName.Substring(newFileName.LastIndexOf('/') + 1, 36)}_{maxWidth}_{maxHeight}.{newFileName.Substring(newFileName.LastIndexOf('.') + 1)}", path);

                    //displayImage.Save(newFileName, img.RawFormat);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    img.Dispose();
                }
            }
        }

        #endregion

        #region 计算新尺寸

        /// <summary>
        /// 计算新尺寸
        /// </summary>
        /// <param name="width">原始宽度</param>
        /// <param name="height">原始高度</param>
        /// <param name="maxWidth">最大新宽度</param>
        /// <param name="maxHeight">最大新高度</param>
        /// <returns>JSON结果集</returns>
        private static Size ResizeImage(int width, int height, int maxWidth, int maxHeight)
        {
            if (maxWidth <= 0)
            {
                maxWidth = width;
            }
            if (maxHeight <= 0)
            {
                maxHeight = height;
            }
            decimal MAX_WIDTH = maxWidth;
            decimal MAX_HEIGHT = maxHeight;
            decimal ASPECT_RATIO = MAX_WIDTH / MAX_HEIGHT;

            int newWidth, newHeight;
            decimal originalWidth = width;
            decimal originalHeight = height;

            if (originalWidth > MAX_WIDTH || originalHeight > MAX_HEIGHT)
            {
                decimal factor;
                if (originalWidth / originalHeight > ASPECT_RATIO)
                {
                    factor = originalWidth / MAX_WIDTH;
                    newWidth = Convert.ToInt32(originalWidth / factor);
                    newHeight = Convert.ToInt32(originalHeight / factor);
                }
                else
                {
                    factor = originalHeight / MAX_HEIGHT;
                    newWidth = Convert.ToInt32(originalWidth / factor);
                    newHeight = Convert.ToInt32(originalHeight / factor);
                }
            }
            else
            {
                newWidth = width;
                newHeight = height;
            }
            return new Size(newWidth, newHeight);
        }

        #endregion

        #region 读取指定路径的 Excel 表格文件列数据

        /// <summary>
        /// 读取指定路径的Excel表格文件列数据
        /// </summary>
        /// <param name="path">Excel表格所在的路径</param>
        /// <param name="sheetIndex">需要读取的Sheet页码序号</param>
        /// <param name="columnIndex">需要读取的列序号</param>
        /// <returns>JSON结果集</returns>
        public static List<string> GetExcelColumnValue(string path, int sheetIndex, int columnIndex)
        {
            List<string> list = new List<string>();

            //读取指定路径的文件
            FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);

            //指定EPPlus使用非商业证书
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            ExcelPackage excel = new ExcelPackage(fileStream);
            ExcelWorksheet sheet = excel.Workbook.Worksheets[sheetIndex];

            try
            {
                // 跳过标题列的读取，从标题头开始读取 (修改 i 的值即可设置读取的起始行)
                for (int i = 2; i <= sheet.Dimension.End.Row; i++)
                {
                    var cell = sheet.Cells[i, columnIndex];
                    if (cell != null && cell.Value != null)
                        list.Add(cell.Value.ToString());
                    else
                        list.Add("");   // 否则填入空值
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                sheet.Dispose();
                excel.Dispose();
                fileStream.Dispose();
            }

            return list;
        }

        #endregion 读取Excel表格列数据

        #region 读取 IFormFile 的 Excel 表格文件列数据

        /// <summary>
        /// 读取指定路径的Excel表格文件列数据
        /// </summary>
        /// <param name="file">Excel表格文件</param>
        /// <param name="sheetIndex">需要读取的Sheet页码序号</param>
        /// <param name="columnIndex">需要读取的列序号</param>
        /// <returns>JSON结果集</returns>
        public static List<string> GetExcelColumnValue(IFormFile file, int sheetIndex, int columnIndex)
        {
            List<string> list = new List<string>();

            //读取指定路径的文件
            Stream fileStream = file.OpenReadStream();

            //指定EPPlus使用非商业证书
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            ExcelPackage excel = new ExcelPackage(fileStream);
            ExcelWorksheet sheet = excel.Workbook.Worksheets[sheetIndex];

            try
            {
                // 跳过标题列的读取，从标题头开始读取 (修改 i 的值即可设置读取的起始行)
                for (int i = 2; i <= sheet.Dimension.End.Row; i++)
                {
                    var cell = sheet.Cells[i, columnIndex];
                    if (cell != null && cell.Value != null)
                        list.Add(cell.Value.ToString());
                    else
                        list.Add("");   // 否则填入空值
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                sheet.Dispose();
                excel.Dispose();
                fileStream.Dispose();
            }

            return list;
        }

        #endregion 读取Excel表格列数据

        #region 图片转换为Btye数组

        /// <summary>
        /// 图片转换为Btye数组
        /// </summary>
        /// <param name="image">image对象</param>
        /// <returns>JSON结果集</returns>
        public static byte[] ImageToBytes(Image image)
        {
            ImageFormat format = image.RawFormat;
            Console.WriteLine($"ImageFormat：{format}");
            using (MemoryStream ms = new MemoryStream())
            {
                if (format.Equals(ImageFormat.Jpeg))
                {
                    Console.WriteLine($"验证 Image 原始格式为：Jpeg，将转换为此格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Jpeg);
                }
                else if (format.Equals(ImageFormat.Png))
                {
                    Console.WriteLine($"验证 Image 原始格式为：Png，将转换为此格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Png);
                }
                else if (format.Equals(ImageFormat.Bmp))
                {
                    Console.WriteLine($"验证 Image 原始格式为：Bmp，将转换为此格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Bmp);
                }
                else if (format.Equals(ImageFormat.Gif))
                {
                    Console.WriteLine($"验证 Image 原始格式为：Gif，将转换为此格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Gif);
                }
                else if (format.Equals(ImageFormat.Icon))
                {
                    Console.WriteLine($"验证 Image 原始格式为：Icon，将转换为此格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Icon);
                }
                else if (format.Equals(ImageFormat.MemoryBmp))
                {
                    Console.WriteLine($"验证 Image 原始格式为：MemoryBmp，将转换为 Bmp 格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Bmp);
                }
                else if (format.Equals(ImageFormat.Bmp))
                {
                    Console.WriteLine($"验证 Image 原始格式为：Bmp，将转换为此格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Bmp);
                }
                else
                {
                    Console.WriteLine($"未确定 Image 原始格式，将默认转换为 Png 格式并存储到 MemoryStream 内");
                    image.Save(ms, ImageFormat.Png);
                }
                byte[] buffer = new byte[ms.Length];
                //Image.Save()会改变MemoryStream的Position，需要重新Seek到Begin
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(buffer, 0, buffer.Length);
                return buffer;
            }
        }

        #endregion

        #region base64 解码转换文件

        /// <summary>
        /// base64 解码转文件
        /// </summary>
        /// <param name="base64Str">文件base64编码</param>
        /// <param name="outPath">生成文件路径</param>
        public static void Base64ToOriFile(string base64Str, string outPath)
        {
            var contents = Convert.FromBase64String(base64Str);
            using (var fs = new FileStream(outPath, FileMode.Create, FileAccess.Write))
            {
                fs.Write(contents, 0, contents.Length);
                fs.Flush();
            }
        }

        /// <summary>
        /// base64 解码转图片
        /// </summary>
        /// <param name="base64Str"></param>
        /// <param name="path"></param>
        /// <param name="imgName"></param>
        /// <returns>JSON结果集</returns>
        public static string Base64ToImage(string base64Str, string path, string imgName)
        {
            string filename = "";                                                                       // 声明一个string类型的相对路径
            string hz = base64Str.Split(',')[0].Split(';')[0].Split('/')[1];                    // 取图片的后缀格式
            string[] str = base64Str.Split(',');                                                      // base64Str为base64完整的字符串，先处理一下需要的字符串
            byte[] imageBytes = Convert.FromBase64String(str[1]);
            MemoryStream memoryStream = new MemoryStream(imageBytes, 0, imageBytes.Length);             // 读入MemoryStream对象
            memoryStream.Write(imageBytes, 0, imageBytes.Length);
            filename = path + imgName + "." + hz;                                        // 所要保存的相对路径及名字
            string tmpRootDir = path;                                                             // 获取程序根目录 
            if (!Directory.Exists(tmpRootDir))
            {
                Directory.CreateDirectory(tmpRootDir);
            }
            string imagesurl2 = tmpRootDir + imgName + "." + hz;                // 转换成绝对路径 
            Image image = Image.FromStream(memoryStream);                    // 转成图片
            string iname = DateTime.Now.ToString("yyMMddhhmmss");        // 图片名称
            image.Save(imagesurl2);                                                              // 将图片存到本地
            return filename;
        }

        #endregion

        #region base64 解码转图片并上传到FTP服务器

        /// <summary>
        /// base64 解码转图片并上传到FTP服务器
        /// </summary>
        /// <param name="base64Str">base64字符串</param>
        /// <param name="path">上传的路径</param>
        /// <param name="imgName">图片文件名称</param>
        /// <returns>JSON结果集</returns>
        public static string Base64ToImageOrUpLoad(string base64Str, string path, string imgName)
        {
            FtpHelper.MakeDir(path);                                                                              // 创建FTP服务器端临时转换目录

            string filename;                                                                                             // 声明一个string类型的相对路径
            string hz = base64Str.Split(',')[0].Split(';')[0].Split('/')[1];                                   // 取图片的后缀格式
            string[] str = base64Str.Split(',');                                                                     // base64Str为base64完整的字符串，先处理一下需要的字符串
            byte[] imageBytes = Convert.FromBase64String(str[1]);
            MemoryStream memoryStream = new MemoryStream(imageBytes, 0, imageBytes.Length);             // 读入MemoryStream对象
            memoryStream.Write(imageBytes, 0, imageBytes.Length);

            //imgName = imgName + "." + hz;                                                              // 设置图片名称
            filename = path + imgName + "." + hz;                                                       // 所要保存的相对路径及名字
            //filename = path + imgName;
            string tmpRootDir = path;                                                                            // 获取程序根目录 

            FtpHelper.FileUpLoad(imageBytes, $"{imgName}.{hz}", path);                       // 上传文件到服务器

            return filename;
        }

        #endregion

        #region base64 解码转图片生成缩略图并上传到FTP服务器

        /// <summary>
        /// base64 解码转缩略图
        /// </summary>
        /// <param name="base64Str"></param>
        /// <param name="newFileName"></param>
        /// <param name="path"></param>
        /// <param name="maxWidth"></param>
        /// <param name="maxHeight"></param>
        /// <returns>JSON结果集</returns>
        public static void Base64ToThumbImg(string base64Str, string newFileName, string path, int maxWidth, int maxHeight)
        {
            // 创建FTP服务器端临时转换目录
            FtpHelper.MakeDir(path);

            // 取图片的后缀格式
            string hz = base64Str.Split(',')[0].Split(';')[0].Split('/')[1];

            // base64Str为base64完整的字符串，先处理一下需要的字符串
            string[] str = base64Str.Split(',');
            byte[] imageBytes = Convert.FromBase64String(str[1]);

            // 读入MemoryStream对象
            MemoryStream memoryStream = new MemoryStream(imageBytes, 0, imageBytes.Length);
            memoryStream.Write(imageBytes, 0, imageBytes.Length);

            // 读取图片字节数组并转换为 image 对象
            Image img = Image.FromStream(new MemoryStream(imageBytes));

            // 重新设置图片大小
            Size newSize = ResizeImage(img.Width, img.Height, maxWidth, maxHeight);
            using Image displayImage = new Bitmap(img, newSize);
            try
            {
                // 将图片重新转换为Byte数组
                byte[] newImageBytes = ImageToBytes(displayImage);

                // 执行上传文件方法
                //FtpHelper.FileUpLoad(newImageBytes, $"{newFileName.Substring(newFileName.LastIndexOf('/') + 1, 36)}_{maxWidth}_{maxHeight}.{newFileName.Substring(newFileName.LastIndexOf('.') + 1)}", path);
                FtpHelper.FileUpLoad(newImageBytes, $"{newFileName.Substring(newFileName.LastIndexOf('/') + 1, 36)}_{maxWidth}_{maxHeight}.{hz}", path);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                img.Dispose();
            }
        }

        #endregion

        #region 上传表单图片文件到FTP服务器

        /// <summary>
        /// 上传表单图片文件到FTP服务器
        /// </summary>
        /// <param name="files">表单文件</param>
        /// <param name="path">上传的路径</param>
        /// <param name="imgName">图片文件名称</param>
        /// <returns>JSON结果集</returns>
        public static string FromFileOrUpLoad(IFormFile files, string path, string imgName)
        {
            FtpHelper.MakeDir(path);                                                                              // 创建FTP服务器端临时转换目录

            string filename;                                                                                             // 声明一个string类型的相对路径
            string hz = files.FileName.Substring(files.FileName.LastIndexOf(".") + 1);       // 取图片的后缀格式
            byte[] imageBytes = new byte[files.Length];                                                  // 初始化图片byte数组

            Stream stream = files.OpenReadStream();
            stream.Position = 0;
            stream.Read(imageBytes, 0, imageBytes.Length);

            //imgName = imgName + "." + hz;                                                           // 设置图片名称
            filename = path + imgName + "." + hz;                                                    // 所要保存的相对路径及名字

            FtpHelper.FileUpLoad(imageBytes, imgName, path);                                 // 上传文件到服务器

            return filename;
        }

        #endregion

        #region 生成表单图片文件的缩略图并上传到FTP服务器

        /// <summary>
        /// 生成表单图片文件的缩略图并上传到FTP服务器
        /// </summary>
        /// <param name="files"></param>
        /// <param name="newFileName"></param>
        /// <param name="path"></param>
        /// <param name="maxWidth"></param>
        /// <param name="maxHeight"></param>
        /// <returns>JSON结果集</returns>
        public static void FromFileToThumbImg(IFormFile files, string newFileName, string path, int maxWidth, int maxHeight)
        {
            // 创建FTP服务器端临时转换目录
            //FtpHelper.MakeDir(path);

            Console.WriteLine($"\n执行上传缩略图方法：FromFileToThumbImg");

            string hz = files.FileName.Substring(files.FileName.LastIndexOf(".") + 1);       // 取图片的后缀格式
            byte[] imageBytes = new byte[files.Length];                                                  // 初始化图片byte数组

            Stream stream = files.OpenReadStream();
            stream.Position = 0;
            stream.Read(imageBytes, 0, imageBytes.Length);

            // 读取图片字节数组并转换为 image 对象
            Console.WriteLine($"\n读取图片字节数组并转换为 image 对象");
            Image img = Image.FromStream(new MemoryStream(imageBytes));

            // 重新设置图片大小
            Console.WriteLine($"\n重新设置图片大小");
            Size newSize = ResizeImage(img.Width, img.Height, maxWidth, maxHeight);
            using Image displayImage = new Bitmap(img, newSize);
            try
            {
                // 将图片重新转换为Byte数组
                Console.WriteLine($"\n将图片重新转换为Byte数组");
                byte[] newImageBytes = ImageToBytes(displayImage);

                // 执行上传文件方法
                Console.WriteLine($"\n将处理好的图片进行上传");
                //FtpHelper.FileUpLoad(newImageBytes, $"{newFileName.Substring(newFileName.LastIndexOf('/') + 1, 36)}_{maxWidth}_{maxHeight}.{newFileName.Substring(newFileName.LastIndexOf('.') + 1)}", path);
                FtpHelper.FileUpLoad(newImageBytes, $"{newFileName.Substring(newFileName.LastIndexOf('/') + 1, 36)}_{maxWidth}_{maxHeight}.{hz}", path);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                img.Dispose();
            }
        }

        #endregion

    }
}